home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 275_01 / lcau21.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-01-01  |  17.6 KB  |  644 lines

  1.  
  2. /* lcau21.c                */
  3. /* (2,1) Linear Cellular Automaton    */
  4.  
  5. /* Reference:                */
  6. /*                    */
  7. /*    Kenneth E. Perry            */
  8. /*    Abstract Mathematical Art        */
  9. /*    BYTE                */
  10. /*    December, 1986            */
  11. /*    pages 181-192            */
  12.  
  13. /*    Copyright (C) 1987        */
  14. /*    Copyright (C) 1988        */
  15. /*    Harold V. McIntosh        */
  16. /*    Gerardo Cisneros S.        */
  17.  
  18. /* G. Cisneros, 4.3.87                        */
  19. /* 10 April 1987 - modified for (4,2) [HVM]            */
  20. /* 26 April 1987 - Multiple menus [HVM]                */
  21. /* 28 April 1987 - back modified to (4,1) [HVM]            */
  22. /* 28 April 1987 - version for XVI Feria de Puebla [HVM]    */
  23. /* 14 May 1987 - modified for (3,1) and general rule [HVM]    */
  24. /* 19 May 1987 - modified for (2,2) [HVM]            */
  25. /* 20 May 1987 - modified for (2,3) [HVM]            */
  26. /* 21 May 1987 - Wolfram rule number [HVM]            */
  27. /* 8 June 1987 - general rule for (4,1) [HVM]             */
  28. /* 12 June 1987 - cartesian product of (2,1) rules [HVM]    */
  29. /* 12 June 1987 - (2,1) rule with memory  [HVM]            */
  30. /* 14 June 1987 - individual cycles of evolution [HVM]        */
  31. /* 17 June 1987 - p-adic representation in plane [HVM]        */
  32. /* 22 June 1987 - 2 speed gliders via 16 transitions [HVM]    */
  33. /* 26 June 1987 - push, pop the rule [HVM]            */
  34. /* 26 June 1987 - conserve position of rule cursor [HVM]    */
  35. /* 27 June 1987 - incremental rule construction [HVM]        */
  36. /* 29 June 1987 - conserve position of cell pointer [HVM]    */
  37. /* 30 June 1987 - mark & unmark transitions, xchg x&X [HVM]    */
  38. /* 25 July 1987 - display and edit de Bruijn diagrams [HVM]    */
  39. /* 27 July 1987 - graph of transition probabilities [HVM]    */
  40. /* 4 September 1987 - PROB21.C for option 't' [HVM]        */
  41. /* 21 October 1987 - program disks disappeared            */
  42. /* 20 December 1987 - program reconstructed from listings    */
  43. /* 20 February 1988 - RIJN21.C for option 'd' [HVM]        */
  44.  
  45. # include <bdos.h>
  46.  
  47. # define COLGRAF     4  /* graph resolution            */
  48. # define T80X25      3  /* text resolution            */
  49. # define WHCYMAG     1  /* color quad for normal screen        */
  50. # define YELREGR     2  /* alternative color palette         */
  51. # define AL        320  /* array length (screen width)        */
  52. # define BD        12    /* maximum number Bernstein coeffs    */ 
  53. # define TS         4  /* distinct sums w/totalistic rule    */
  54. # define DS         8  /* number of distinct neighborhoods    */
  55. # define KK         2  /* number of states per cell        */
  56. # define NX          7    /* number of sample rules        */
  57.  
  58. char xrule[NX][KK][KK][KK];
  59.  
  60. char ixrule[NX][DS]=
  61.  
  62.     "00110011",    /* interfaces of 2 vel    */
  63.     "00110011",
  64.     "00111011",    /* mottled background    */
  65.     "00111001",    /* (0*102211200)* still */
  66.     "01101000",    /* Rule 22        */
  67.     "10010010",    /* Rule 73        */
  68.     "11111101"    /* 2 glider on 1 bkgrnd    */
  69.  
  70.     ;
  71.  
  72. char   rule[DS+1], ascrule[KK][KK][KK];
  73. char   trule[TS]="0000";
  74. int    binrule[KK][KK][KK], arule[DS], arr1[AL], arr2[AL];
  75. int    stat[KK], stal, stac, star;
  76. int    ix0, iy0;                    /* origin for pen moves */
  77. double wmul[KK], wmvl[KK];                /* left mass point */
  78. double wmur[KK], wmvr[KK];                /* right mass point */
  79. double bp[BD];
  80.  
  81. main()
  82. {
  83. int  i, j, i0, i1, i2;
  84. int  more = 'r';
  85. char a, b, c;
  86.  
  87. for (i=0; i<NX; i++) {                    /* copy to 3-index array */
  88. i0=0; i1=0; i2=0;
  89. for (j=0; j<DS; j++) {
  90.   xrule[i][i0][i1][i2]=ixrule[i][j];
  91.   i2++;
  92.   if (i2>KK-1) {i2=0; i1++;};
  93.   if (i1>KK-1) {i1=0; i0++;};
  94.   if (i0>KK-1) {i0=0; };
  95. };};
  96.  
  97.  
  98.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  99.  
  100.     tuto();
  101.     while (!kbdst()) rand();                /* wait for keypress */
  102.     kbdin();                        /* ignore it */
  103.     videomode(T80X25);
  104.     videoscroll(3,0,5,71,0,3);                /* menu on blue background */
  105.     videoscroll(19,0,24,71,0,3);
  106.     xtoasc(rand()%NX);
  107.     rule[DS]=0;
  108.     ranlin();                        /* random initial array */
  109.  
  110.     while (more!='n') {                    /* execute multiple runs */
  111.     rmenu();
  112.     lmenu();
  113.     while (0<1) {                    /* set up one run */
  114.     c=kbdin();
  115.     if (c=='g') break;                    /* go draw graph */
  116.     if (c=='q') more='n';                /* quit for good */
  117.     if (more=='n') break;
  118.     switch (c) {
  119.     case '@':                    /* numbered tot rule */
  120.         nutoto(numin(0));
  121.         totoasc();
  122.         rmenu();
  123.         videocursor(0,4,0);
  124.         break;
  125.     case '$':                    /* dozen totalistics */
  126.         j=numin(0);
  127.         for (i=0; i<12; i++) {
  128.           nutoto(j+i);
  129.           totoasc();
  130.           ranlin();
  131.           evolve();
  132.           };
  133.         videomode(T80X25);
  134.         rmenu();
  135.         lmenu();
  136.         break;
  137.     case 'T':                    /* totalistic rule */
  138.         xblnk();
  139.         tmenu();
  140.         edtrule();
  141.         totoasc();
  142.         for (i0=0; i0<KK; i0++) {
  143.         for (i1=0; i1<KK; i1++) {
  144.         for (i2=0; i2<KK; i2++) {
  145.         ascrule[i0][i1][i2]=trule[i0+i1+i2];
  146.         };};};
  147.         videocursor(0,4,0);
  148.         rmenu();
  149.         xmenu(totonu(0));
  150.         break;
  151.     case 't':                    /* probability calculation */
  152.         edtri();
  153.         rmenu();
  154.         lmenu();
  155.         break;
  156.         case 'r':                    /* edit rule */    
  157.         xblnk();
  158.         edrule();
  159.         videocursor(0,4,0);
  160.         rmenu();
  161.         break;
  162.         case 'l':                    /* edit cell string */
  163.         xblnk();
  164.         edline();
  165.         videocursor(0,3,0);
  166.         lmenu();
  167.         break;
  168.         case '#':                    /* read stored rule */
  169.         xmenu(NX);
  170.         xtoasc(lim(1,numin(0),NX)-1);
  171.         rmenu();
  172.             break;
  173.     case 'D':                    /* run through samples */
  174.         for (i=0; i<NX; i++) {
  175.           xmenu(i);
  176.           xtoasc(i);
  177.           ranlin();
  178.           evolve();
  179.           };
  180.         videomode(T80X25);
  181.         rmenu();
  182.         break;
  183.     case 'd':                    /* de Bruijn diagram */
  184.         edijn();
  185.         rmenu();
  186.         lmenu();
  187.         break;
  188.         case 'u':                    /* sparse init arry */
  189.         xblnk();
  190.         for (i=0; i<AL; i++) arr1[i]=0;
  191.         arr1[AL/4]=1;
  192.             arr1[AL/2]=1;
  193.             arr1[(3*AL)/4]=1;
  194.             arr1[(3*AL)/4+2]=1;
  195.         lmenu();
  196.             break;
  197.     case 'w':                    /* Wolfram rulw # */
  198.         i=numin(0);
  199.         wmenu(i);
  200.         for (i0=0; i0<KK; i0++) {
  201.         for (i1=0; i1<KK; i1++) {
  202.         for (i2=0; i2<KK; i2++) {
  203.           ascrule[i0][i1][i2]='0'+i%2;
  204.           i/=2;
  205.         };};};
  206.         rmenu();
  207.         break;
  208.     case 'x':                    /* random rule */
  209.         xblnk();
  210.         for (i0=0; i0<KK; i0++) {
  211.         for (i1=0; i1<KK; i1++) {
  212.         for (i2=0; i2<KK; i2++) {
  213.           if ((KK*(KK*i0+i1)+i2)%4 == 0) i=rand();
  214.           ascrule[i0][i1][i2]='0'+i%2;
  215.           i/=2;
  216.         };};};
  217.         rmenu();
  218.         break;
  219.     case 'y':                    /* random line */
  220.         xblnk();
  221.         ranlin();
  222.             lmenu();
  223.         break;
  224.     case 'Y':                    /* symmetrize rule */
  225.         for (i0=0; i0<KK; i0++) {
  226.         for (i1=0; i1<KK; i1++) {
  227.         for (i2=0; i2<KK; i2++) {
  228.         ascrule[i2][i1][i0]=ascrule[i0][i1][i2];      
  229.         };};};
  230.         break;
  231.     case 'B':                    /* begin barrier */
  232.         a=kbdin();
  233.         b=kbdin();
  234.         ascrule[0][a-'0'][b-'0']=a;
  235.         ascrule[1][a-'0'][b-'0']=a;
  236.         ascrule[2][a-'0'][b-'0']=a;
  237.         rmenu();
  238.         break;
  239.     case 'E':                    /* end barrier */
  240.         a=kbdin();
  241.         b=kbdin();
  242.         ascrule[a-'0'][b-'0'][0]=b;
  243.         ascrule[a-'0'][b-'0'][1]=b;
  244.         ascrule[a-'0'][b-'0'][2]=b;
  245.         rmenu();
  246.         break;
  247.     case 'L':                    /* left glider link */
  248.         a=kbdin();
  249.         b=kbdin();
  250.         c=kbdin();
  251.         ascrule[a-'0'][b-'0'][c-'0']=c;
  252.         rmenu();
  253.         break;
  254.     case 'R':                    /* left glider link */
  255.         a=kbdin();
  256.         b=kbdin();
  257.         c=kbdin();
  258.         ascrule[a-'0'][b-'0'][c-'0']=a;
  259.         rmenu();
  260.         break;
  261.     case 'S':                    /* still life link */
  262.         a=kbdin();
  263.         b=kbdin();
  264.         c=kbdin();
  265.         ascrule[a-'0'][b-'0'][c-'0']=b;
  266.         rmenu();
  267.         break;
  268.     case '.':                    /* one cycle of evolution */
  269.         asctobin();
  270.         onegen(AL);
  271.         lmenu();
  272.         break;
  273.     case '=':
  274.         for (i=1; i<8;  i++) {
  275.         for (j=0; j<40; j++) arr1[40*i+j]=arr1[j];};
  276.         lmenu();
  277.         break;
  278.     case '~':
  279.         for (i=1; i<16;  i++) {
  280.         for (j=0; j<20; j++) arr1[20*i+j]=arr1[j];};
  281.         lmenu();
  282.         break;
  283.         default: break;
  284.         };
  285.     };
  286.     if (more=='n') break;
  287.     do {
  288.     evolve();
  289.     videocursor(0,0,0);
  290.     scrstr("More?");
  291.     videocursor(0,0,34);
  292.     scrstr("y/n/cr");
  293.     more=kbdin();
  294.     } while (more=='\015');
  295.     videomode(T80X25);                    /* reset the screen */
  296.     if (more=='n') break;
  297.     };
  298.   videomode(T80X25);}    
  299.  
  300. /* edit the rule */
  301. edrule() {
  302. char c;
  303. int  i, i0, i1, i2;
  304.  
  305. i=6; i0=0; i1=0, i2=0;
  306.     while (0<1) {
  307.         videocursor(0,3,i);
  308.         c = kbdin();
  309.         if (c == '\015') break;                /* carriage return exits */
  310.         switch (c) {
  311.         case '0':  case '1':                /* state */
  312.         ascrule[i0][i1][i2] = c;
  313.             i2++;
  314.         if (i2>KK-1) {i2=0; i1++;};
  315.         if (i1>KK-1) {i1=0; i0++;};
  316.         if (i0>KK-1) {i2=0; };
  317.             videocattr(0,c,3,1);
  318.             if (i<6+DS) i++;
  319.             break;
  320.         case ' ': case '\315':                /* space = advance */
  321.             i2++;
  322.         if (i2>KK-1) {i2=0; i1++;};
  323.         if (i1>KK-1) {i1=0; i0++;};
  324.         if (i0>KK-1) {i2=0; };
  325.             if (i<6+DS) i++;
  326.             break;
  327.         case '\010': case '\313':            /* backspace */
  328.         if (i2!=0) i2--; else {i2=KK-1;
  329.         if (i1!=0) i1--; else {i1=KK-1;
  330.         if (i0!=0) i0--; else {i0=KK-1;
  331.         };};};
  332.             if (i>6) i--;
  333.             break;
  334.     default: break;
  335.         };
  336.     };
  337. }
  338.  
  339. /* edit totalistic rule */
  340. edtrule() {char c; int  i;
  341.     i=0;
  342.     while (i<TS) {
  343.     c=trule[i];
  344.     videocursor(0,3,56+i);
  345.         videocattr(0,c,3,1);
  346.         c = kbdin();
  347.         if (c == '\015') break;
  348.         switch (c) {
  349.           case '0': case '1':                /* state */
  350.             trule[i]=c;
  351.             videocattr(0,c,5,1);
  352.         i++;
  353.             break;
  354.           case ' ': case '\315':            /* space = advance */
  355.         i++;
  356.             break;
  357.           case '\010': case '\313':            /* backspace */
  358.             if (i!=0) i--;
  359.         break;
  360.       default: break;
  361.           };
  362.     };
  363. }
  364.  
  365. /* edit the line */
  366. edline() {
  367. char c;
  368. int  i, j, k, ii, jj;
  369.  
  370.     videocursor(0,19,0);
  371.     scrstr("insert states using 0, 1,");
  372.     videocursor(0,20,0);
  373.     scrstr("move cursor with n(north), s(south), e(east), w(west), or");
  374.     videocursor(0,21,0);
  375.     scrstr("with keyboard arrows. Space, backspace move right and left.");
  376.     videocursor(0,22,0);
  377.     scrstr("( seeks left margin, < absolutely, { up one line, [ down one line");
  378.     videocursor(0,23,0);
  379.     scrstr(") seeks right margin, > absolutely, } up one line, ] down one line");
  380.     videocursor(0,24,0);
  381.     scrstr("carriage return exits");
  382.     jj=4;
  383.     ii=1;
  384.     while (0<1) {
  385.     ii=lim(1,ii,40);
  386.     jj=lim(1,jj,8);
  387.     j=jj-1;
  388.     i=ii-1;
  389.     videocursor(0,j+9,i);
  390.     c=kbdin();
  391.     if (c == '\015') {videoscroll(19,0,24,70,0,3); break;};
  392.     switch (c) {
  393.     case '0':  case '1':        /* enter  state */
  394.        arr1[40*j+i]=c-'0'; ii++; break;
  395.     case 's': case '\012': case '\320':          jj++; break;    /* down - next line */
  396.     case 'n': case '\013': case '\310':          jj--; break;    /* up   - last line */
  397.     case 'e': case '\014': case '\315': case ' ': ii++; break;    /* space = advance  */
  398.     case 'w': case '\010': case '\313':          ii--; break;    /* backspace */
  399.     case '<': ii=1;  jj=1;  break;  /* absolute left */
  400.     case '{': ii=1;  jj--;  break;  /* left one row up */
  401.     case '(': ii=1;         break;  /* left this row */
  402.     case '[': ii=1;  jj++;  break;  /* left next row */
  403.     case '>': ii=40; jj=40; break;  /* absolute right */
  404.     case '}': ii=40; jj--;  break;  /* right one row up */
  405.     case ')': ii=40;        break;  /* right this row */
  406.     case ']': ii=40; jj++;  break;  /* right next row */
  407.     default: break;
  408.         };
  409.     videocursor(0,j+9,0);
  410.     for (k=0; k<40; k++) videoputc('0'+arr1[40*j+k],1);
  411.     };
  412. }
  413.  
  414. /* display a screen of evolution */
  415. evolve() {
  416. int i, j;
  417.   videomode(COLGRAF);                    /* erase the screen */
  418.   videocursor(0,0,0);                    /* top text line */
  419.   scrstr("Rule: ");
  420.   scrrul();
  421.   woruno(0,28);                        /* Wolfram rule number */
  422.   asctobin();
  423.   for (j=8; j<200; j++) videodot(j,AL-1,2);
  424.   for (j=8; j<200; j++) {                /* evolve for 192 generations */
  425.     for (i=0; i<AL; i++) videodot(j,i,arr1[i]);
  426.     onegen(AL);
  427.     if (kbdst()) {kbdin(); break;};
  428.     };
  429. }
  430.  
  431. /* copy ascrule over to binrul */
  432. asctobin() {int i, i0, i1, i2;
  433.     for (i=0; i<DS; i++) {arule[i] = rule[i]-'0';};
  434.     for (i0=0; i0<KK; i0++) {
  435.     for (i1=0; i1<KK; i1++) {
  436.     for (i2=0; i2<KK; i2++) {
  437.       binrule[i0][i1][i2]=ascrule[i0][i1][i2]-'0';
  438.       };};};
  439. }
  440.  
  441. /* evolution for one generation */
  442. onegen(j) int j; {int i;
  443.   if (j<2) return;
  444.   arr2[0]=binrule[arr1[j-1]][arr1[0]][arr1[1]];
  445.   for (i=1; i<j-1; i++) arr2[i]=binrule[arr1[i-1]][arr1[i]][arr1[i+1]];
  446.   arr2[j-1]=binrule[arr1[j-2]][arr1[j-1]][arr1[0]];
  447.   for (i=0;  i<j; i++) arr1[i]=arr2[i];
  448. }
  449.  
  450. /* generate a random line of cells in arr1 */
  451. ranlin() {int i, c;
  452. for (i=0; i<AL; i++) {
  453.   if (i%8 == 0) c=rand();
  454.   arr1[i]=c%2; c/=2;};
  455. }
  456.  
  457. /* tutorial and Help screen */
  458. tuto() {
  459.     videomode(T80X25);
  460.     videocursor(0,2,0);
  461.     scrstr("<Copyright (C) 1987, 1988 - H.V.McIntosh, G.Cisneros S.>");
  462.     videocursor(0,4,0);
  463.     scrstr("              *** LIFE in One Dimension ***");
  464.     videocursor(0,6,0);
  465.     scrstr("Two States - Black(0), Cyan(1).");
  466.     videocursor(0,8,0);
  467.     scrstr("First neighbors - one on each side, three altogether.");
  468.     videocursor(0,10,0);
  469.     scrstr("Complete transition rule - random, edited, or stored.");
  470.     videocursor(0,12,0);
  471.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  472.     videocursor(0,14,0);
  473.     scrstr("Submenus in options t(probabilities) and d(de Bruijn)");
  474.     videocursor(0,15,0);
  475.     scrstr("will be displayed in response to typing ?");
  476.     videocursor(0,17,0);
  477.     scrstr("Use any key to terminate a display in progress.");
  478.     videocursor(0,21,0);
  479.     scrstr("Now, ... press any key to continue.");
  480. }
  481.  
  482. /* rule menu */
  483. rmenu() {
  484.     videocursor(0,0,0);
  485.     scrstr("      00001111");
  486.     videocursor(0,1,0);
  487.     scrstr("      00110011");
  488.     videocursor(0,2,0);
  489.     scrstr("      01010101");
  490.     videocursor(0,3,0);
  491.     scrstr("Rule: ");
  492.     scrrul();
  493.     videocursor(0,3,16);
  494.     printf("  ");
  495.     videocursor(0,3,16);
  496.     if (istot()==1) printf("%2d",totonu(0));
  497.     videocursor(0,5,0);
  498.     scrstr("   r(rule), l(line), #nn(stored), g(graph), q(quit), t(prob),");
  499.     videocursor(0,6,0);
  500.     scrstr("   x(rand rule), y(rand line), u(unit line), d(deBruijn)");
  501.     videocursor(0,7,0);
  502.     scrstr("   wnn(Wolfram #), @nn(tot/rul), $nn(12 tot/rul), T(ed tot/rul).");
  503.     videocursor(0,5,0);
  504.     }
  505.  
  506. /* totalistic rule menu*/
  507. tmenu() {
  508.     videocursor(0,2,50);
  509.     scrstr("      0..1");
  510.     videocursor(0,3,50);
  511.     scrstr("rule: ");
  512.     tscrrul();
  513.     videocursor(0,3,56);
  514.     }
  515.  
  516. /* line menu */
  517. lmenu() {int i, j;
  518.     for (j=0; 40*j<AL; j++) {
  519.     videocursor(0,9+j,0);
  520.     for (i=0; i<40; i++) videoputc('0'+arr1[40*j+i],1);
  521.     }
  522.     videocursor(0,5,0); }
  523.  
  524. /* display Wolfram rule number */
  525. wmenu(n) int n;
  526. {char xx[4]; int i, nn;  
  527.     nn=sprintf(xx,"%3d",n);
  528.     videocursor(0,2,40);
  529.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  530.     videocursor(0,2,40); }
  531.  
  532. /* display rule number */
  533. xmenu(n) int n;
  534. {char xx[4]; int i, nn;  
  535.     nn=sprintf(xx,"%3d",n);
  536.     videocursor(0,1,40);
  537.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  538.     videocursor(0,1,40); }
  539.  
  540. /* clear screen space for rule numbers */
  541. xblnk() {
  542.     videocursor(0,1,40);
  543.     scrstr("     ");
  544.     videocursor(0,2,40);
  545.     scrstr("     ");
  546.     videocursor(0,5,0); }
  547.  
  548. /* copy saved rule #n into active rule */
  549. xtoasc(n) int n; { int i0, i1, i2;
  550.     xmenu(n+1);
  551.     for (i0=0; i0<KK; i0++) {
  552.     for (i1=0; i1<KK; i1++) {
  553.     for (i2=0; i2<KK; i2++) {
  554.     ascrule[i0][i1][i2] = xrule[n][i0][i1][i2];        /* random sample rule */
  555.     };};}; }
  556.  
  557. /* change totalistic rule to general rule */
  558. totoasc() {
  559. int i0, i1, i2;
  560. for (i0=0; i0<KK; i0++) {
  561. for (i1=0; i1<KK; i1++) {
  562. for (i2=0; i2<KK; i2++) {
  563. ascrule[i0][i1][i2]=trule[i0+i1+i2];
  564. };};};
  565. }
  566.  
  567. /* change decimal totalistic rule to sum values */
  568. nutoto(x) int x; {int i;
  569. for (i=0; i<TS; i++) {trule[i]=x%2+'0'; x/=2;};}
  570.  
  571. /* change sum values to decimal totalistic rule */
  572. int totonu(i) int i; {int r;
  573.   if (i<TS) r=(trule[i]-'0')+2*totonu(i+1); else r=0;
  574.   return r; }
  575.  
  576. /* test whether a rule is totalistic */
  577. int istot() {int i0, i1, i2, l;
  578.     l=1;
  579.     trule[0]=ascrule[0][0][0];
  580.     trule[1]=ascrule[1][0][0];
  581.     trule[2]=ascrule[1][1][0];
  582.     trule[3]=ascrule[1][1][1];
  583.     for (i0=0; i0<KK; i0++) {
  584.     for (i1=0; i1<KK; i1++) {
  585.     for (i2=0; i2<KK; i2++) {
  586.     if (ascrule[i0][i1][i2]!=trule[i0+i1+i2]) l=0;      
  587.     };};};
  588.     return l; }
  589.  
  590. /* limit j to interval (i,k) */
  591. int lim(i,j,k) int i, j, k;
  592.     {if (i>=j) return i; if (k<=j) return k; return j;}
  593.  
  594. /* display the rule number on the screen */
  595. scrrul() {int i0, i1, i2;
  596.   for (i0=0; i0<KK; i0++) {
  597.   for (i1=0; i1<KK; i1++) {
  598.   for (i2=0; i2<KK; i2++) {
  599.   videoputc(ascrule[i0][i1][i2],1);      
  600.   };};}; }
  601.  
  602. /* turn ascrule into its Wolfram number and place on screen at (i,j) */
  603. woruno(i,j) int i, j; {
  604. char xx[4];
  605. int  k, l, i0, i1, i2;
  606.   k=0;
  607.   for (i0=KK-1; i0>=0; i0--) {
  608.   for (i1=KK-1; i1>=0; i1--) {
  609.   for (i2=KK-1; i2>=0; i2--) {
  610.     k=2*k+(ascrule[i0][i1][i2]-'0');
  611.     };};};
  612.   k=sprintf(xx,"%3d",k);
  613.   videocursor(0,i,j);
  614.   for (l=0; l<k; l++) videoputc(xx[l],1);
  615. }
  616.  
  617. /* display totalistic rule number by sum */
  618. tscrrul() {int i;
  619.   for (i=0; i<TS; i++) {videoputc(trule[i]); }; }
  620.  
  621. /* write a string in graphics mode */
  622. scrstr(s) char *s;
  623.   {for (; *s != '\0'; s++) videoputc(*s,1); }
  624.  
  625. /* keyboard status */
  626. int kbdst() {return(bdos(11) & 0xFF);}
  627.  
  628. /* direct keyboard input, no echo */
  629. kbdin() {int c;
  630.   if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  631.   return(c);
  632. }
  633.  
  634. /* read number from keyboard */
  635. int numin(n) int n; {char c;
  636.   c=kbdin();
  637.   if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  638. }
  639.  
  640. # include "prob21.c"
  641. # include "rijn21.c"
  642.  
  643. /* end */
  644.